﻿using System.Collections.Generic;
using DependencyAnalysis;
using DependencyAnalysis.DataModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests
{
    [TestClass]
    public class HalsteadCacheTypeTest : AnalyzerTestBase
    {
        private HalsteadCache _halsteadCache;
        private DependencyModel _model;
        private TypeDescriptor _typeSwitchAndGet;
        private TypeDescriptor _typeSwitchAndSwitch;
        private TypeDescriptor _typeNoMembers;
        private TypeDescriptor _inheritingType;

        [TestInitialize]
        public void Initialize()
        {
            var submoduleDescriptor = new SubmoduleDescriptor
            {
                Identifier = "<<<XYZ",
                FullName = "<<<XYZ"
            };
            _model = new DependencyModel();
            _halsteadCache = new HalsteadCache();
            _typeSwitchAndGet = new TypeDescriptor
            {
                Identifier = "<<<Test1",
                FullName = "<<<Test1",
                Submodule = submoduleDescriptor
            };
            var getter = HalsteadCacheMemberTest.PrepareGetter(_model);
            var switchMethod = HalsteadCacheMemberTest.PrepareSwitch(_model);
            getter.ImplementingType = _typeSwitchAndGet;
            switchMethod.ImplementingType = _typeSwitchAndGet;
            _typeSwitchAndGet.Members.Add(getter);
            _typeSwitchAndGet.Members.Add(switchMethod);
            _model.Add(_typeSwitchAndGet);

            _typeSwitchAndSwitch = new TypeDescriptor
            {
                Identifier = "<<<Test2",
                FullName = "<<<Test2",
                Submodule = submoduleDescriptor
            };

            var switchMethod1 = HalsteadCacheMemberTest.PrepareSwitch(_model);
            switchMethod1.ImplementingType = _typeSwitchAndSwitch;
            _typeSwitchAndSwitch.Members.Add(switchMethod1);
            _typeSwitchAndSwitch.Members.Add(switchMethod1);
            _model.Add(_typeSwitchAndSwitch);

            _typeNoMembers = new TypeDescriptor
            {
                Identifier = "<<<Test3",
                FullName = "<<<Test3",
                Visibility = NodeVisibility.Public,
                AbstractionType = AbstractionType.Abstract,
                Submodule = submoduleDescriptor
            };

            _model.Add(_typeNoMembers);

            _inheritingType = new TypeDescriptor
            {
                Identifier = "<<<Test4",
                FullName = "<<<Test4",
                Visibility = NodeVisibility.Public,
                AbstractionType = AbstractionType.Abstract,
                Submodule = submoduleDescriptor,
                InheritedTypes = new List<TypeDescriptor> { _typeNoMembers, _typeSwitchAndSwitch }
            };

            _model.Add(_inheritingType);
        }

        [TestMethod]
        public void WhenDifferentMembersThenCombineDistinctOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndGet, _model);

            Assert.AreEqual(5, entry.DistinctOperands);
        }

        [TestMethod]
        public void WhenDifferentMembersThenCombineDistinctOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndGet, _model);

            Assert.AreEqual(5, entry.DistinctOperators);
        }

        [TestMethod]
        public void WhenDifferentMembersThenCombineTotalOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndGet, _model);

            Assert.AreEqual(8, entry.TotalOperands);
        }

        [TestMethod]
        public void WhenDifferentMembersThenCombineTotalOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndGet, _model);

            Assert.AreEqual(7, entry.TotalOperators);
        }

        [TestMethod]
        public void WhenDuplicateMembersThenCombineDistinctOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndSwitch, _model);

            Assert.AreEqual(4, entry.DistinctOperands);
        }

        [TestMethod]
        public void WhenDuplicateMembersThenCombineDistinctOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndSwitch, _model);

            Assert.AreEqual(4, entry.DistinctOperators);
        }

        [TestMethod]
        public void WhenDuplicateMembersThenCombineTotalOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndSwitch, _model);

            Assert.AreEqual(12, entry.TotalOperands);
        }

        [TestMethod]
        public void WhenDuplicateMembersThenCombineTotalOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeSwitchAndSwitch, _model);

            Assert.AreEqual(11, entry.TotalOperators);
        }

        [TestMethod]
        public void WhenNoMembersThenNamespaceAndTypeAreDistinctOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeNoMembers, _model);

            Assert.AreEqual(2, entry.DistinctOperands);
        }

        [TestMethod]
        public void WhenNoMembersTypeThenAccessorsAreDistinctOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeNoMembers, _model);

            Assert.AreEqual(3, entry.DistinctOperators);
        }

        [TestMethod]
        public void WhenNoMembersTypeThenNamespaceAndTypeAreTotalOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeNoMembers, _model);

            Assert.AreEqual(2, entry.TotalOperands);
        }

        [TestMethod]
        public void WhenInheritanceTypeThenDontCountForTotalOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_inheritingType, _model);

            Assert.AreEqual(4, entry.TotalOperators);
        }

        [TestMethod]
        public void WhenInheritanceTypeThenCountForTotalOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_inheritingType, _model);

            Assert.AreEqual(4, entry.TotalOperands);
        }

        [TestMethod]
        public void WhenInheritanceTypeThenCountForDistinctOperands()
        {
            var entry = _halsteadCache.GetCacheEntry(_inheritingType, _model);

            Assert.AreEqual(4, entry.DistinctOperands);
        }

        [TestMethod]
        public void WhenInheritanceTypeThenDontCountForDistinctOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_inheritingType, _model);

            Assert.AreEqual(4, entry.DistinctOperators);
        }

        [TestMethod]
        public void WhenNoMembersTypeThenThenAccessorsAreTotalOperators()
        {
            var entry = _halsteadCache.GetCacheEntry(_typeNoMembers, _model);

            Assert.AreEqual(3, entry.TotalOperators);
        }

        [TestMethod]
        public void WhenCreateCacheEntryForProjectThenNoException()
        {
            _halsteadCache.GetCacheEntry(Model.Project, Model);
        }
    }
}
